package com.xiaozhen.tcp.adapter;

import com.alibaba.fastjson.JSONObject;
import com.xiaoleilu.hutool.collection.CollectionUtil;
import com.xiaozhen.common.core.domain.driver.ParseTcpAttribute;
import com.xiaozhen.common.core.domain.driver.ParseTcpAttributeFormula;
import com.xiaozhen.common.core.domain.driver.ParseGroup;
import com.xiaozhen.common.core.utils.ConvertUtils;
import com.xiaozhen.common.core.utils.StringUtils;
import com.xiaozhen.common.redis.utils.RedisUtils;
import com.xiaozhen.tcp.util.AttributeValueUtils;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;

/**
 * @Author: zhenweisheng
 * @Date: 2020/8/7 9:55
 * @Description:
 */
@Slf4j
public class PointChannelHandler extends ChannelHandlerAdapter {

    private RedisUtils redisUtils;
    private Map<Integer, ParseGroup> parseGroupMap;
    private List<ParseTcpAttribute> parseAttributeList;

    public PointChannelHandler(RedisUtils redisUtils, Map<Integer, ParseGroup> parseGroupMap,
                               List<ParseTcpAttribute> parseAttributeList) {
        this.redisUtils = redisUtils;
        this.parseGroupMap = parseGroupMap;
        this.parseAttributeList = parseAttributeList;
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.info("--- [发生异常] 释放资源: {} ---", cause.getMessage());
        // todo
        ctx.close();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("--- 成功建立连接 ---");
        ctx.writeAndFlush("Server connect success");
    }

    /**
     * 读取到信息 进行处理
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            byte[] msgInfo = (byte[]) msg;
            //消息解析处理
            //用来记录所有信息的json
            JSONObject jsonObject = new JSONObject(true);
            //最终结果的json
            JSONObject resultJson = new JSONObject(true);
            parsingMessage(msgInfo, parseAttributeList, resultJson, jsonObject);
            System.out.println(resultJson.toJSONString());
            //判断是否需要下发数据
            //把数据存到redis里，然后这里取出发送
        } catch (Exception e) {
            log.error("处理数据发生异常");
            e.printStackTrace();
        }
    }

    /**
     * 消息解析处理
     * <p>
     * 一层层的进行数据解析
     * 先最外层  然后子属性解析...
     *
     * @param
     * @throws Exception
     */
    public void parsingMessage(byte[] msgInfo, List<ParseTcpAttribute> parseAttributeList,
                               JSONObject resultJson, JSONObject jsonObject) throws Exception {
        for (ParseTcpAttribute parseAttribute : parseAttributeList) {
            //得到属性对应的字节数组
            byte[] attributeBytes = AttributeValueUtils.getAttributeBytes(msgInfo, parseAttribute.getStartPoint(),parseAttribute.getEndPoint());
            if (attributeBytes == null) {
                continue;
            }
            //字节数组需要转换的值类型
            Object objectValue = ConvertUtils.bytes2Value(parseAttribute.getAttributeType(), attributeBytes);
            //进行转换得到最终值
            List<ParseTcpAttributeFormula> formulaStepList = parseAttribute.getFormulaStepList();
            Object attributeValue;
            if (CollectionUtil.isNotEmpty(formulaStepList)) {
                attributeValue = AttributeValueUtils.getAttributeValue(objectValue,formulaStepList);
            } else {
                attributeValue = objectValue;
            }
            //是否有子属性
            if (CollectionUtil.isNotEmpty(parseAttribute.getChildren())) {
                //是否要进行分组 分组字段值
                String groupField = parseAttribute.getGroupField();
                if (StringUtils.isNotBlank(groupField)) {
                    //得到分类值
                    Object groupValue = jsonObject.get(groupField);
                    //如果分类值和某一个的属性相同 则解析  不同不做处理
                    for (ParseTcpAttribute parseAttributeChild : parseAttribute.getChildren()) {
                        if (parseAttributeChild.getAttributeName().equals(groupValue)) {
                            JSONObject resultJson2 = new JSONObject(true);
                            parsingMessage((byte[]) objectValue, parseAttributeChild.getChildren(), resultJson2,jsonObject);
                            resultJson.put(parseAttribute.getAttributeName(), resultJson2);
                        }
                    }
                } else {
                    JSONObject resultJson2 = new JSONObject(true);
                    parsingMessage((byte[]) objectValue, parseAttribute.getChildren(), resultJson2,jsonObject);
                    resultJson.put(parseAttribute.getAttributeName(), resultJson2);
                }
            } else {
                //将最终结果转换为结果类型
                String attributeResultType = parseAttribute.getAttributeResultType();
                Object value;
                if (attributeResultType != null && !"null".equalsIgnoreCase(attributeResultType)) {
                    value = ConvertUtils.value(attributeResultType, attributeValue.toString());
                } else {
                    value = attributeValue;
                }
                jsonObject.put(parseAttribute.getAttributeName(), value);
                resultJson.put(parseAttribute.getAttributeName(), value);
            }
        }
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        log.info("--- channelReadComplete ---");
        ctx.flush();
    }

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        ctx.write(msg, promise);
    }
}
